/*
 RNAvigator is a tool for visualizing secondary structure of RNA
 Copyright 2012 Elias La Cour & Peter Bertelsen

 This file is part of RNAvigator.

 RNAvigator is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 RNAvigator is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with RNAvigator.  If not, see <http://www.gnu.org/licenses/>.
 */

/*
 * Created on Dec 14, 2011, 1:05:22 PM
 */
package rnavigator.view;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;
import rnavigator.controller.Controller;
import rnavigator.controller.PopupListener;
import rnavigator.model.LoadFile;
import rnavigator.model.Model;
import rnavigator.model.Structure;

/**
 *
 * @author Elias la Cour & Peter Bertelsen
 */
public class GUI extends javax.swing.JFrame {

    private Model model;
    private Controller controller;
    private String header = "";
//    private int screenHeight;
//    private int screenWidth;
//    private int adjustedScreenHeight;
    private boolean jpanelButton = true;

    public GUI() {
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
              } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(GUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(GUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(GUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(GUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        setTitle("RNAvigator");
        initComponents();

    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jToolBar1 = new javax.swing.JToolBar();
        menu_open = new javax.swing.JButton();
        menu_open_reactivity = new javax.swing.JButton();
        menu_save = new javax.swing.JButton();
        menu_circular_feynman = new javax.swing.JButton();
        menu_linear_feynman = new javax.swing.JButton();
        menu_statistics = new javax.swing.JButton();
        jButton8 = new javax.swing.JButton();
        jButton9 = new javax.swing.JButton();
        jButton10 = new javax.swing.JButton();
        menu_help = new javax.swing.JButton();
        jLabel1 = new javax.swing.JLabel();
        jLayeredPane2 = new javax.swing.JLayeredPane();
        jTabbedPane1 = new javax.swing.JTabbedPane();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        jToolBar1.setBackground(new java.awt.Color(204, 204, 204));
        jToolBar1.setBorder(null);
        jToolBar1.setFloatable(false);
        jToolBar1.setRollover(true);
        jToolBar1.setBorderPainted(false);

        menu_open.setIcon(new javax.swing.ImageIcon(getClass().getResource("/resources/document-open-8.png"))); // NOI18N
        menu_open.setToolTipText("Open file...");
        menu_open.setFocusable(false);
        menu_open.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        menu_open.setMaximumSize(new java.awt.Dimension(32, 32));
        menu_open.setMinimumSize(new java.awt.Dimension(32, 32));
        menu_open.setPreferredSize(new java.awt.Dimension(32, 32));
        menu_open.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        menu_open.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                menu_openActionPerformed(evt);
            }
        });
        jToolBar1.add(menu_open);

        menu_open_reactivity.setIcon(new javax.swing.ImageIcon(getClass().getResource("/resources/document-open-8.png"))); // NOI18N
        menu_open_reactivity.setToolTipText("Open reactivity file...");
        menu_open_reactivity.setFocusable(false);
        menu_open_reactivity.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        menu_open_reactivity.setMaximumSize(new java.awt.Dimension(32, 32));
        menu_open_reactivity.setMinimumSize(new java.awt.Dimension(32, 32));
        menu_open_reactivity.setPreferredSize(new java.awt.Dimension(32, 32));
        menu_open_reactivity.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        menu_open_reactivity.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                menu_open_reactivityActionPerformed(evt);
            }
        });
        jToolBar1.add(menu_open_reactivity);

        menu_save.setIcon(new javax.swing.ImageIcon(getClass().getResource("/resources/document-save-as-6.png"))); // NOI18N
        menu_save.setToolTipText("Export diagram...");
        menu_save.setFocusable(false);
        menu_save.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        menu_save.setMaximumSize(new java.awt.Dimension(32, 32));
        menu_save.setMinimumSize(new java.awt.Dimension(32, 32));
        menu_save.setPreferredSize(new java.awt.Dimension(32, 32));
        menu_save.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        menu_save.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                menu_saveActionPerformed(evt);
            }
        });
        jToolBar1.add(menu_save);

        menu_circular_feynman.setIcon(new javax.swing.ImageIcon(getClass().getResource("/resources/Feynman_circ_icon.png"))); // NOI18N
        menu_circular_feynman.setToolTipText("Circular Feynman Diagram");
        menu_circular_feynman.setFocusable(false);
        menu_circular_feynman.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        menu_circular_feynman.setMaximumSize(new java.awt.Dimension(32, 32));
        menu_circular_feynman.setMinimumSize(new java.awt.Dimension(32, 32));
        menu_circular_feynman.setPreferredSize(new java.awt.Dimension(32, 32));
        menu_circular_feynman.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        menu_circular_feynman.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                menu_circular_feynmanActionPerformed(evt);
            }
        });
        jToolBar1.add(menu_circular_feynman);

        menu_linear_feynman.setIcon(new javax.swing.ImageIcon(getClass().getResource("/resources/Feynman_lin_icon.png"))); // NOI18N
        menu_linear_feynman.setToolTipText("Linear Feynman Diagram");
        menu_linear_feynman.setFocusable(false);
        menu_linear_feynman.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        menu_linear_feynman.setMaximumSize(new java.awt.Dimension(32, 32));
        menu_linear_feynman.setMinimumSize(new java.awt.Dimension(32, 32));
        menu_linear_feynman.setPreferredSize(new java.awt.Dimension(32, 32));
        menu_linear_feynman.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        menu_linear_feynman.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                menu_linear_feynmanActionPerformed(evt);
            }
        });
        jToolBar1.add(menu_linear_feynman);

        menu_statistics.setIcon(new javax.swing.ImageIcon(getClass().getResource("/resources/Statistics_icon.png"))); // NOI18N
        menu_statistics.setToolTipText("Statistics");
        menu_statistics.setFocusable(false);
        menu_statistics.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        menu_statistics.setMaximumSize(new java.awt.Dimension(32, 32));
        menu_statistics.setMinimumSize(new java.awt.Dimension(32, 32));
        menu_statistics.setPreferredSize(new java.awt.Dimension(32, 32));
        menu_statistics.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jToolBar1.add(menu_statistics);

        jButton8.setIcon(new javax.swing.ImageIcon(getClass().getResource("/resources/Customize-icon.png"))); // NOI18N
        jButton8.setToolTipText("Customize");
        jButton8.setFocusable(false);
        jButton8.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        jButton8.setMaximumSize(new java.awt.Dimension(32, 32));
        jButton8.setMinimumSize(new java.awt.Dimension(32, 32));
        jButton8.setPreferredSize(new java.awt.Dimension(32, 32));
        jButton8.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jToolBar1.add(jButton8);

        jButton9.setIcon(new javax.swing.ImageIcon(getClass().getResource("/resources/motifs-icon.png"))); // NOI18N
        jButton9.setToolTipText("Find motifs");
        jButton9.setFocusable(false);
        jButton9.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        jButton9.setMaximumSize(new java.awt.Dimension(32, 32));
        jButton9.setMinimumSize(new java.awt.Dimension(32, 32));
        jButton9.setPreferredSize(new java.awt.Dimension(32, 32));
        jButton9.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jToolBar1.add(jButton9);

        jButton10.setIcon(new javax.swing.ImageIcon(getClass().getResource("/resources/edit-icon.png"))); // NOI18N
        jButton10.setToolTipText("Edit og interact with diagram layout");
        jButton10.setFocusable(false);
        jButton10.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        jButton10.setMaximumSize(new java.awt.Dimension(32, 32));
        jButton10.setMinimumSize(new java.awt.Dimension(32, 32));
        jButton10.setPreferredSize(new java.awt.Dimension(32, 32));
        jButton10.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jToolBar1.add(jButton10);

        menu_help.setIcon(new javax.swing.ImageIcon(getClass().getResource("/resources/system-help-3.png"))); // NOI18N
        menu_help.setToolTipText("Help contents");
        menu_help.setFocusable(false);
        menu_help.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        menu_help.setMaximumSize(new java.awt.Dimension(32, 32));
        menu_help.setMinimumSize(new java.awt.Dimension(32, 32));
        menu_help.setPreferredSize(new java.awt.Dimension(32, 32));
        menu_help.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        menu_help.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                menu_helpActionPerformed(evt);
            }
        });
        jToolBar1.add(menu_help);

        jLabel1.setText("Status bar");
        jLabel1.setBorder(new javax.swing.border.LineBorder(new java.awt.Color(0, 0, 0), 1, true));

        jLayeredPane2.setBorder(javax.swing.BorderFactory.createEtchedBorder());

        jTabbedPane1.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
        jTabbedPane1.setDoubleBuffered(true);
        jTabbedPane1.setBounds(0, 0, 1340, 700);
        jLayeredPane2.add(jTabbedPane1, javax.swing.JLayeredPane.DEFAULT_LAYER);

        org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(jToolBar1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 1341, Short.MAX_VALUE)
            .add(jLabel1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 1341, Short.MAX_VALUE)
            .add(jLayeredPane2)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(layout.createSequentialGroup()
                .add(jToolBar1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(jLayeredPane2, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 700, Short.MAX_VALUE)
                .add(2, 2, 2)
                .add(jLabel1))
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void menu_openActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menu_openActionPerformed
        final JFileChooser fc = new JFileChooser();
        int returnVal = fc.showOpenDialog(GUI.this);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            File file = fc.getSelectedFile();
            try {
                model.createAndSetStructure(new LoadFile(file));
                if (model.getStructure() != null) {
                    newTab(model.getStructure(), (byte) 2);
                }
            } catch (IOException ex) {
                JOptionPane.showMessageDialog(this, "File format not supported or file contents garbled.");
                //              Logger.getLogger(GUI.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }//GEN-LAST:event_menu_openActionPerformed
    private void menu_helpActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menu_helpActionPerformed

//        JTextArea jtext = new JTextArea("This is the amazing help of the amazin' app.");
//        jtext.setSize(200, jLayeredPane2.getHeight());
//        jtext.setLineWrap(true);
//        jLayeredPane2.add(jtext);
//        jLayeredPane2.setLayer(jtext, 1);

        if (jpanelButton) {
            jpanelButton = false;


            jp = new JPanel(new BorderLayout());

            JButton close = new JButton("close");

            jp.add(close, BorderLayout.SOUTH);

//        jp.setSize(200, 200);
            jp.setBackground(new Color(200, 200, 200));

            jp.setBounds(jLayeredPane2.getWidth() - 300, 0, 300, jLayeredPane2.getHeight());

            jLayeredPane2.add(jp);


            jLayeredPane2.setLayer(jp, 1);
        } else {
            jpanelButton = true;
            jLayeredPane2.remove(jp);
            repaint();
        }

    }//GEN-LAST:event_menu_helpActionPerformed

    private void menu_linear_feynmanActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menu_linear_feynmanActionPerformed
        Structure structure = getSelectedCanvas().getStructure();
        newTab(structure, (byte) 1);
    }//GEN-LAST:event_menu_linear_feynmanActionPerformed

    private void menu_circular_feynmanActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menu_circular_feynmanActionPerformed
        Structure structure = getSelectedCanvas().getStructure();
        newTab(structure, (byte) 2);
    }//GEN-LAST:event_menu_circular_feynmanActionPerformed

    private void menu_saveActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menu_saveActionPerformed
        //currently saves the part of the diagram that is visible. E.g. if zoomed in, only the zoomed in part is stored 
        String ext = "";
        String filter_name;
        String name;
        final JFileChooser fc = new JFileChooser();
        fc.setAcceptAllFileFilterUsed(false);
        fc.setFileFilter(new FileNameExtensionFilter("PNG File", "png"));
        int returnVal = fc.showSaveDialog(GUI.this);

        if (returnVal == JFileChooser.APPROVE_OPTION) {
            name = fc.getSelectedFile().getAbsolutePath();
            filter_name = fc.getFileFilter().getDescription();

            if (filter_name.equals("PNG File")) {
                ext = "png";
                name = name + "." + ext;
                System.out.println(name);
            } else {
                JOptionPane.showMessageDialog(this, "Error in saving file", "ERROR", JOptionPane.ERROR_MESSAGE);
            }
            BufferedImage bi = getSelectedCanvas().getDiagram();
            try {
                ImageIO.write(bi, ext, new File(name));
            } catch (IOException ex) {
                Logger.getLogger(StructureCanvas.class.getName()).log(Level.SEVERE, null, ex);
            }
        } else {
            System.out.println("Save command cancelled by user.");
        }
    }//GEN-LAST:event_menu_saveActionPerformed

    private void menu_open_reactivityActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menu_open_reactivityActionPerformed
        final JFileChooser fc = new JFileChooser();
        int returnVal = fc.showOpenDialog(GUI.this);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            File file = fc.getSelectedFile();
            try {
                model.addReactivity(new LoadFile(file));
                if (model.getStructure() != null) {
                    newTab(model.getStructure(), (byte) 2);
                }
            } catch (IOException ex) {
                JOptionPane.showMessageDialog(this, "Shape Reactivity file format not supported or file contents garbled.");
            }
        }
    }//GEN-LAST:event_menu_open_reactivityActionPerformed

    /**
     * @return the model
     */
    public Model getModel() {
        return model;
    }

    /**
     * @param model the model to set
     */
    public void setModel(Model model) {
        this.model = model;
    }

    /**
     * @return the controller
     */
    public Controller getController() {
        return controller;
    }

    /**
     * @param controller the controller to set
     */
    public void setController(Controller controller) {
        this.controller = controller;
    }

    /**
     * @return Returns the currently selected StructureCanvas
     */
    public boolean isStructureCanvas() {
        return jTabbedPane1.getSelectedComponent() instanceof StructureCanvas;
    }

    public StructureCanvas getStructureCanvas() {
        return (StructureCanvas) jTabbedPane1.getSelectedComponent();
    }

    /**
     * @param header the header to set
     */
    public void setHeader(String header) {
        this.header = header;
    }

    public void newTab(Structure structure, byte view) {
        StructureCanvas canvas;
        popupMenu = new JPopupMenu();
        menuItem = new JMenuItem("Close Tab");
        ActionListener al = new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                int i = jTabbedPane1.getSelectedIndex();
                jTabbedPane1.remove(i);
                //throw new UnsupportedOperationException("Not supported yet.");
            }
        };
        menuItem.addActionListener(al);
        popupMenu.add(menuItem);
        popupListener = new PopupListener(popupMenu);
        //Structure structure = model.getStructure();
        canvas = new StructureCanvas(this, jTabbedPane1.getSize());
        canvas.setView(view);
        canvas.addMouseListener(popupListener);
        canvas.addMouseListener(new java.awt.event.MouseAdapter() {

            @Override
            public void mousePressed(java.awt.event.MouseEvent evt) {
                controller.mousePressed(evt);
            }

            @Override
            public void mouseReleased(java.awt.event.MouseEvent evt) {
                controller.mouseReleased(evt);
            }

            @Override
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                controller.mouseClicked(evt);
            }
        });
        canvas.addMouseMotionListener(new java.awt.event.MouseAdapter() {

            @Override
            public void mouseDragged(java.awt.event.MouseEvent evt) {
                controller.mouseDragged(evt);
            }
        });
        canvas.addMouseWheelListener(new java.awt.event.MouseAdapter() {

            @Override
            public void mouseWheelMoved(java.awt.event.MouseWheelEvent evt) {
                controller.mousewheelMoved(evt);
            }
        });

        canvas.setStructure(structure);
        jTabbedPane1.insertTab(structure.getFilename(), null, canvas, structure.getHeader(), 0);
        jTabbedPane1.addMouseListener(popupListener);
        jTabbedPane1.setSelectedIndex(0);
        canvas.repaint();
    }

    public StructureCanvas getSelectedCanvas() {
        int i = jTabbedPane1.getSelectedIndex();
        StructureCanvas canvas = (StructureCanvas) jTabbedPane1.getComponentAt(i);
        return canvas;
    }
    private JPanel jp;
    MouseListener popupListener;
    JPopupMenu popupMenu;
    JMenuItem menuItem;
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton jButton10;
    private javax.swing.JButton jButton8;
    private javax.swing.JButton jButton9;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLayeredPane jLayeredPane2;
    private javax.swing.JTabbedPane jTabbedPane1;
    private javax.swing.JToolBar jToolBar1;
    private javax.swing.JButton menu_circular_feynman;
    private javax.swing.JButton menu_help;
    private javax.swing.JButton menu_linear_feynman;
    private javax.swing.JButton menu_open;
    private javax.swing.JButton menu_open_reactivity;
    private javax.swing.JButton menu_save;
    private javax.swing.JButton menu_statistics;
    // End of variables declaration//GEN-END:variables
}
